package com.qzboot.backend.web.common.shiro;

import com.qzboot.common.constant.SysConst;
import com.qzboot.facade.entity.SysUser;
import com.qzboot.facade.entity.SysUserToken;
import com.qzboot.facade.service.SysAuthenticationService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * @author zengzhihong
 */
@Component
public class SysAuthenticationRealm extends AuthorizingRealm {

    @Lazy
    @Reference
    private SysAuthenticationService sysAuthenticationService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof SysAuthenticationToken;
    }

    /**
     * 授权(接口保护，验证接口调用权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUser user = (SysUser) principals.getPrimaryPrincipal();
        Set<String> permsSet = sysAuthenticationService.listUserPerms(user.getId());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }

    /**
     * 认证(登录时调用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = (String) authenticationToken.getPrincipal();
        // 根据accessToken，查询用户token信息
        SysUserToken sysUserToken = sysAuthenticationService.getUserTokenByToken(token);
        if (sysUserToken == null || sysUserToken.getExpireTime().getTime() < System.currentTimeMillis()) {
            // token已经失效
            throw new IncorrectCredentialsException("登录失效，请重新登录");
        }
        // 查询用户信息
        SysUser user = sysAuthenticationService.getUserById(sysUserToken.getUserId());
        // 账号被锁定
        if (!SysConst.NORMAL.equals(user.getState())) {
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        return new SimpleAuthenticationInfo(user, token, getName());
    }
}
